package paper.parse;

import java.util.regex.*;
import java.util.Vector;

import paper.token.TT;
import paper.token.Token;
import paper.parse.TokenInputStream;

public class BibToken implements TokenInputStream {
    Vector<Token> tokens;
    int index;
    TokenStream parent;
    
    static Pattern tokenSep = Pattern.compile("[\\.,:;]");
    
    public BibToken(Vector<Token>bibList, int first, int last, Pattern bibStart, TokenStream p) {
        parent = p;
        tokens = new Vector<Token>();
        int from = bibList.get(first).from;
        if (bibStart != null) {                // these refs have a key.
            Matcher m = bibStart.matcher(p.substring(from));
            if (m.find()) {
                tokens.add(new Token(this, from, m.end(), 0, TT.KEY));
//                System.out.println("+ " + m.end() + tokens.get(0));
                while (bibList.get(first).from < from + m.end()) {
                    first++;
                }
            } else {
                //fixme. Key not found. Bad news. Should be one level up.
            }
        }
        for(int i = first; i < last; i++) {
            Token t;
            boolean dot = false;
            double probs[] = {1,1,1,1};
            int l = 0;
            from = 0;
            do {
                t = bibList.get(i);
//                    System.out.println("= " + t);
                if (t.t == TT.NUMBER) {
                    break;
                }
                if (l == 0) {
                    from = t.from;
                }
                if (t.probs != null) {
                    for(int j = 0; j < 4; j++) {
                        probs[j] *= t.probs[j];
                    }
                }
                String r = t.getRawText();
                l += t.length;
                Matcher m = tokenSep.matcher(r);
                if (m.find()) {
                    if (r.indexOf(".") != -1) {
                        dot = true;
                    }
                    break;
                }
                i++;
            } while (i < last);
            if (l != 0) {
                double sum = 0;
                int maxJ = -1;
                double maxProb = 0;
                for(int j = 0; j < 4; j++) {
                    sum += probs[j];
                    if (probs[j] > maxProb) {
                        maxProb = probs[j];
                        maxJ = j;
                    }
                }
                for(int j = 0; j < 4; j++) {
                    probs[j] /= sum;
                }
                maxProb /= sum;
                if (maxProb < 0.26) maxJ = -1;
                Token newT = new Token(this, from, l, l,
                                       maxJ == 0 ? TT.AUTHOR :
                                       maxJ == 1 ? TT.TITLE :
                                       maxJ == 2 ? TT.AFFILIATION :
                                       maxJ == 3 ? TT.WHERE : TT.UNKNOWN);
                newT.probs = probs;
                tokens.add(newT);
//                    System.out.println("" + probs[0] +"  " + probs[1] + " " + probs[2] + " " + probs[3] + " " + maxJ + " " +newT);
            }
            if (t.t == TT.NUMBER) {
                tokens.add(t);
//                    System.out.println("+ " + t);
            }
            if (dot) {
                tokens.add(new Token(this, from+l, 0, 0, TT.DOT));
//                    System.out.println("DOT");
            }
        }
        index = 0;
/*            for (int i = 0; i < tokens.size(); i++) {
              System.out.println("" + tokens.get(i));
              }
              System.out.println("+-+-+- EOF " + tokens.size() + " tokens");*/
    }
    
    public boolean atEnd() {
        return index >= tokens.size();
    }
    
    public Token next() {
        return tokens.get(index++);
    }
    
    public int mark() {
        return index;
    }
    
    public void reset(int mark) {
        index = mark;
    }
    
    public int length() {
        return tokens.size();
    }
    
    public String substring(int from, int to) {
        return parent.substring(from,to);
    }
}
